package com.shanzmoo.platform.manage.api.manager.merchant;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shanzmoo.base.bean.PageRespBase;
import com.shanzmoo.base.bean.SHttpResponse;
import com.shanzmoo.base.util.CollectionUtil;
import com.shanzmoo.base.util.JYFException;
import com.shanzmoo.core.manager.base.AliSmsManager;
import com.shanzmoo.db.module.base.entity.SAreaEntity;
import com.shanzmoo.db.module.base.service.ISAreaService;
import com.shanzmoo.db.module.merchant.domain.base.BaseInfoDomain;
import com.shanzmoo.db.module.merchant.domain.dto.MerchantSettlementInfoDto;
import com.shanzmoo.db.module.merchant.domain.query.*;
import com.shanzmoo.db.module.merchant.domain.vo.*;
import com.shanzmoo.db.module.merchant.domain.vo.base.MerchantBaseInfoVo;
import com.shanzmoo.db.module.merchant.domain.vo.base.MerchantSettlementInfoVo;
import com.shanzmoo.db.module.merchant.entity.*;
import com.shanzmoo.db.module.merchant.service.*;
import com.shanzmoo.db.module.pay.entity.SBankEntity;
import com.shanzmoo.db.module.pay.entity.SBusinessEntity;
import com.shanzmoo.db.module.pay.service.ISBankService;
import com.shanzmoo.db.module.pay.service.ISBusinessService;
import com.shanzmoo.pay.domain.request.merchantRequest.SaobeiMerchantAddRequest;
import com.shanzmoo.pay.domain.request.merchantRequest.SaobeiMerchantCheckRequest;
import com.shanzmoo.pay.domain.response.merchantResponse.SaobeiMerchantAddResponse;
import com.shanzmoo.pay.domain.response.merchantResponse.SaobeiMerchantCheckResponse;
import com.shanzmoo.pay.manager.SaobeiMerchantManager;
import com.shanzmoo.pay.manager.SaobeiStoreManager;
import com.shanzmoo.pay.manager.SaobeiTerminalManager;
import com.shanzmoo.pay.util.ApiConstants;
import com.shanzmoo.pay.util.RandomUtils;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
public class MerchantInfoManager {
    // 入驻商户操作服务
    private final IMerchantInfoService iMerchantInfoService;
    // 行业类目操作服务
    private final ISBusinessService isBusinessService;
    // 城市列表操作服务
    private final ISAreaService isAreaService;
    // 银行列表服务信息
    private final ISBankService isBankService;
    // 短信发送服务
    private final AliSmsManager aliSmsManager;
    // 商户门店操作信息
    private final IMerchantShopService iMerchantShopService;
    // 商户台卡操作信息
    private final IMerchantTerminalService iMerchantTerminalService;
    // 商户变更单操作信息
    private final IMerchantChangeInfoService iMerchantChangeInfoService;
    // 商户基本信息操作信息
    private final IMerchantBaseInfoService iMerchantBaseInfoService;
    // 商户结算信息变更操作信息
    private final IMerchantBillingInfoService iMerchantBillingInfoService;
    // 商户操作日志操作信息
    private final IMerchantOperLogService iMerchantOperLogService;
    // 扫呗商户接口管理
    private final SaobeiMerchantManager saobeiMerchantManager;
    // 扫呗门店接口管理
    private final SaobeiStoreManager saobeiStoreManager;
    // 扫呗终端（台卡）接口管理
    private final SaobeiTerminalManager saobeiTerminalManager;

    /**
     * 根据查询条件查询入驻商户明细信息
     *
     * @param query
     * @return
     */
    public SHttpResponse<MerchantInfoDetailVo> selectMerchantInfo(MerchantInfoQuery query) {
        // 1、查询数据库数据信息
        MerchantInfoEntity merchantInfoEntity = iMerchantInfoService.lambdaQuery()
                .eq(StringUtils.isNotBlank(query.getCode()), MerchantInfoEntity::getCode, query.getCode())
                .eq(StringUtils.isNotBlank(query.getMobile()), MerchantInfoEntity::getMobile, query.getMobile())
                .one();
        if (merchantInfoEntity == null) {
            return SHttpResponse.fail(100006, "未查询到商户信息");
        }
        // 2、组装返回值信息
        MerchantInfoDetailVo merchantInfoDetailVo = new MerchantInfoDetailVo();
        BeanUtils.copyProperties(merchantInfoEntity, merchantInfoDetailVo);
        return SHttpResponse.ok(merchantInfoDetailVo);
    }

    /**
     * 分页查询入驻商户信息
     *
     * @param query 入驻商户查询条件信息
     * @return
     */
    public SHttpResponse<PageRespBase<MerchantSimpleInfoVo>> selectMerchantInfos(@RequestBody MerchantInfoQuery query) {
        log.info("分页查询入驻商户信息入参信息为：{}", JSONObject.toJSONString(query));
        // 1、根据条件查询数据信息
        Page<MerchantInfoEntity> page = iMerchantInfoService.lambdaQuery()
                .eq(StringUtils.isNotBlank(query.getCode()), MerchantInfoEntity::getCode, query.getCode())
                .eq(StringUtils.isNotBlank(query.getMobile()), MerchantInfoEntity::getMobile, query.getMobile())
                .like(StringUtils.isNotBlank(query.getName()), MerchantInfoEntity::getName, query.getName())
                .between(query.getSubmitStartTime() != null, MerchantInfoEntity::getCreateTime, query.getSubmitStartTime(), query.getSubmitEndTime())
                .eq(query.getStatus() != null, MerchantInfoEntity::getStatus, query.getStatus())
                .orderByDesc(MerchantInfoEntity::getCreateTime)
                .page(new Page<>(query.getPageNum(), query.getPageSize()));
        // 3、组装数据信息
        PageRespBase<MerchantSimpleInfoVo> respBase = new PageRespBase<MerchantSimpleInfoVo>();
        respBase.setCurrPage(query.getPageNum());
        respBase.setPageSize(query.getPageSize());
        respBase.setTotalCount(page.getTotal());
        respBase.setTotalPage(page.getTotal() % page.getSize() == 0 ? page.getTotal() / page.getSize() : page.getTotal() / page.getSize() + 1);
        List<MerchantSimpleInfoVo> merchantSimpleInfoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            page.getRecords().forEach(item -> {
                MerchantSimpleInfoVo simpleInfoVo = new MerchantSimpleInfoVo();
                BeanUtils.copyProperties(item, simpleInfoVo);
                merchantSimpleInfoList.add(simpleInfoVo);
            });
        }
        respBase.setList(merchantSimpleInfoList);
        return SHttpResponse.ok(respBase);
    }

    /**
     * 更新入驻商户基本信息
     *
     * @param merchantManageBaseInfoVo 待修改的入驻商户信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Integer> updateMerchantInfo(@RequestBody MerchantManageBaseInfoVo merchantManageBaseInfoVo) throws JYFException {
        // 1、构建需要修改的商户原基本信息
        MerchantInfoEntity merchantInfoEntity = new MerchantInfoEntity();
        BeanUtils.copyProperties(merchantManageBaseInfoVo, merchantInfoEntity);
        // 2、更新数据信息
        boolean update = iMerchantInfoService.lambdaUpdate()
                .eq(MerchantInfoEntity::getCode, merchantInfoEntity.getCode())
                .update(merchantInfoEntity);
        if (!update) {
            log.error("更新入驻商户基本信息异常，待更新数据为：{}", JSON.toJSONString(merchantInfoEntity));
            throw new JYFException("更新入驻商户基本信息异常");
        }
        // 3、写操作日志记录表
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(merchantManageBaseInfoVo, "商户平台修改入驻商户基本信息", 11);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok(1);
    }

    /**
     * 修改入驻商户证照信息
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Integer> updateMerchantManageLicenceInfo(@RequestBody MerchantManageLicenceInfoVo merchantManageLicenceInfoVo) throws JYFException {
        // 1、构建需要修改的商户原基本信息
        MerchantInfoEntity merchantInfoEntity = new MerchantInfoEntity();
        BeanUtils.copyProperties(merchantManageLicenceInfoVo, merchantInfoEntity);
        // 2、更新数据信息
        boolean update = iMerchantInfoService.lambdaUpdate()
                .eq(MerchantInfoEntity::getCode, merchantInfoEntity.getCode())
                .update(merchantInfoEntity);
        if (!update) {
            log.error("修改入驻商户证照信息，待更新数据为：{}", JSON.toJSONString(merchantInfoEntity));
            throw new JYFException("修改入驻商户证照信息异常");
        }
        // 3、写操作日志记录表
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(merchantManageLicenceInfoVo, "商户平台修改入驻证照信息", 12);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok(1);
    }

    /**
     * 获取行业类别信息
     *
     * @return
     */
    public SHttpResponse<List<BusinessVo>> selectBusinessInfo(BusinessQuery query) {
        // 1、获取当前制定条件的所有行业类目信息
        List<SBusinessEntity> businessEntities = isBusinessService.lambdaQuery()
                .eq(SBusinessEntity::getDeleted, 0)
                .eq(query.getBusinessLevel() != null, SBusinessEntity::getBusinessLevel, query.getBusinessLevel())
                .eq(StringUtils.isNotBlank(query.getBusinessParentCode()), SBusinessEntity::getBusinessParentCode, query.getBusinessParentCode())
                .list();
        if (CollectionUtil.isEmpty(businessEntities)) {
            log.error("查询行业类别信息为空，查询条件为：{}", JSONObject.toJSONString(query));
            return SHttpResponse.fail(100009, "查询行业类别信息为空");
        }
        // 2、组装返回值信息
        List<BusinessVo> businessVos = new ArrayList<>();
        businessEntities.stream().forEach(item -> {
            BusinessVo businessVo = new BusinessVo();
            BeanUtils.copyProperties(item, businessVo);
            businessVos.add(businessVo);
        });
        return SHttpResponse.ok(businessVos);
    }

    /**
     * 获取地区信息
     *
     * @return
     */
    public SHttpResponse<List<AreaVo>> selectAreaInfo(@RequestBody AreaQuery query) {
        // 1、获取当前制定条件的所有地区信息
        List<SAreaEntity> areaEntities = isAreaService.lambdaQuery()
                .eq(SAreaEntity::getDeleted, 0)
                .eq(StringUtils.isNotBlank(query.getAreaCode()), SAreaEntity::getAreaCode, query.getAreaCode())
                .eq(StringUtils.isNotBlank(query.getAreaParentCode()), SAreaEntity::getAreaParentCode, query.getAreaParentCode())
                .like(StringUtils.isNotBlank(query.getAreaName()), SAreaEntity::getAreaName, query.getAreaName())
                .eq(StringUtils.isNotBlank(query.getAreaLevel()), SAreaEntity::getAreaLevel, query.getAreaLevel())
                .orderByDesc(query.getOrderNum() != null, SAreaEntity::getOrderNum)
                .list();
        if (CollectionUtil.isEmpty(areaEntities)) {
            log.error("获取地区信息为空，查询条件为：{}", JSONObject.toJSONString(query));
            return SHttpResponse.fail(100009, "获取地区信息为空");
        }
        // 2、组装返回值信息
        List<AreaVo> areaVos = new ArrayList<>();
        areaEntities.stream().forEach(item -> {
            AreaVo areaVo = new AreaVo();
            BeanUtils.copyProperties(item, areaVo);
            areaVos.add(areaVo);
        });
        return SHttpResponse.ok(areaVos);
    }

    /**
     * 通过银卡编码获取支行信息等
     *
     * @return
     */
    public SHttpResponse<List<BankVo>> selectBank(@RequestBody BankQuery query) {
        // 1、获取当前制定条件的所有银行信息
        List<SBankEntity> bankEntities = isBankService.lambdaQuery()
                .eq(SBankEntity::getDeleted, 0)
                .eq(StringUtils.isNotBlank(query.getBankCode()), SBankEntity::getBankCode, query.getBankCode())
                .eq(StringUtils.isNotBlank(query.getBankName()), SBankEntity::getBankName, query.getBankName())
                .eq(StringUtils.isNotBlank(query.getBankParentCode()), SBankEntity::getBankParentCode, query.getBankParentCode())
                .eq(query.getBankLevel() != null, SBankEntity::getBankLevel, query.getBankLevel())
                .list();
        if (CollectionUtil.isEmpty(bankEntities)) {
            log.error("获取支行信息为空，查询条件为：{}", JSONObject.toJSONString(query));
            return SHttpResponse.fail(100009, "获取支行信息为空");
        }
        // 2、组装返回值信息
        List<BankVo> bankVos = new ArrayList<>();
        bankEntities.stream().forEach(item -> {
            BankVo bankVo = new BankVo();
            BeanUtils.copyProperties(item, bankVo);
            bankVos.add(bankVo);
        });
        return SHttpResponse.ok(bankVos);
    }

    /**
     * 查询变更单入驻商户基本信息
     *
     * @param query 查询条件
     * @return
     */
    public SHttpResponse<MerchantManageBaseInfosVo> selectMerchantBaseInfo(@RequestBody BaseQuery query) {
        // 1、查询变更单信息
        MerchantChangeInfoEntity changeInfoEntity = iMerchantChangeInfoService.lambdaQuery()
                .eq(MerchantChangeInfoEntity::getId, query.getId())
                .one();
        // 2、根据变更单信息获取对应的入驻商户基本信息
        MerchantBaseInfoEntity newBaseInfo = iMerchantBaseInfoService.lambdaQuery()
                .eq(MerchantBaseInfoEntity::getId, changeInfoEntity.getChangeLinkId())
                .one();
        // 3、构造返回值信息
        MerchantManageBaseInfosVo baseInfosVo = initMerchantManageBaseInfosVo(newBaseInfo);
        return SHttpResponse.ok(baseInfosVo);
    }

    /**
     * 更新变更单入驻商户基本信息
     *
     * @param merchantBaseInfo 待修改的入驻商户信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Integer> updateMerchantBaseInfo(@RequestBody MerchantBaseInfoVo merchantBaseInfo) throws JYFException {
        // 1、获取商户原基本信息
        MerchantInfoEntity merchantInfoEntity = iMerchantInfoService.lambdaQuery()
                .eq(MerchantInfoEntity::getCode, merchantBaseInfo.getCode())
                .one();
        if (merchantInfoEntity == null) {
            log.error("获取商户原基本信息异常，查询条件为：{}", JSONObject.toJSONString(merchantBaseInfo));
            throw new JYFException("获取商户原基本信息为空");
        }
        // 2、原基本信息存入基本信息备份表
        MerchantBaseInfoEntity merchantBaseInfoEntity = new MerchantBaseInfoEntity();
        initMerchantManageBaseInfoEntity(merchantBaseInfoEntity, merchantInfoEntity);
        // 3、当前新数据入库
        BeanUtils.copyProperties(merchantBaseInfo, merchantBaseInfoEntity);
        merchantBaseInfoEntity.setId(null);
        iMerchantBaseInfoService.save(merchantBaseInfoEntity);
        // 4、写商户变更表
        // 4.1、初始化商户变更记录信息实体
        MerchantChangeInfoEntity merchantChangeInfoEntity = initMerchantChangeInfo(merchantBaseInfo);
        merchantChangeInfoEntity.setChangeLinkId(merchantBaseInfoEntity.getId());
        boolean save = iMerchantChangeInfoService.save(merchantChangeInfoEntity);
        // 5、写操作日志记录表
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(merchantBaseInfo, "变更单入驻商户基本信息", 14);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok(1);
    }

    /**
     * 查询变更单结算信息
     *
     * @return
     */
    public SHttpResponse<MerchantSettlementInfosVo> selectMerchantSettlementInfo(@RequestBody BaseQuery query) {
        // 1、查询变更单信息
        MerchantChangeInfoEntity changeInfoEntity = iMerchantChangeInfoService.lambdaQuery()
                .eq(MerchantChangeInfoEntity::getId, query.getId())
                .one();
        // 2、根据变更单信息获取对应的入驻商户结算信息
        MerchantBillingInfoEntity newBaseInfo = iMerchantBillingInfoService.lambdaQuery()
                .eq(MerchantBillingInfoEntity::getId, changeInfoEntity.getChangeLinkId())
                .one();
        // 3、构造返回值信息
        MerchantSettlementInfosVo baseInfosVo = initMerchantSettlementInfosVo(newBaseInfo);
        return SHttpResponse.ok(baseInfosVo);
    }

    /**
     * 修改变更单结算信息
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Boolean> updateMerchantSettlementInfo(@RequestBody MerchantSettlementInfoDto settlementInfo) throws JYFException {
        // 1、查询当前商户是否存在待审核信息，若存在，则不允许再次修改
        List<MerchantChangeInfoEntity> list = iMerchantChangeInfoService.lambdaQuery()
                .eq(MerchantChangeInfoEntity::getCode, settlementInfo.getCode())
                .ne(MerchantChangeInfoEntity::getChangeStatus, 3)
                .list();
        if (CollectionUtil.isNotEmpty(list)) {
            log.error("当前存在正在审核的商户结算信息，不能再次更改商户信息");
            return SHttpResponse.fail(100004, "当前存在正在审核的商户结算信息，不能再次更改商户信息");
        }
        // 2、获取商户原基本信息
        MerchantInfoEntity merchantInfoEntity = iMerchantInfoService.lambdaQuery()
                .eq(MerchantInfoEntity::getCode, settlementInfo.getCode())
                .one();
        if (merchantInfoEntity == null) {
            log.error("获取商户原基本信息异常，查询条件为：{}", JSONObject.toJSONString(settlementInfo));
            throw new JYFException("获取商户原基本信息为空");
        }
        // 3、商户结算信息存入商户结算备份表
        MerchantBillingInfoEntity merchantBillingInfoEntity = new MerchantBillingInfoEntity();
        BeanUtils.copyProperties(settlementInfo, merchantBillingInfoEntity);
        // 3、原数据入审核变更单
        initMerchantBillingInfoEntity(merchantBillingInfoEntity, merchantInfoEntity);
        merchantBillingInfoEntity.setMerchantId(settlementInfo.getCode());
        merchantBillingInfoEntity.setId(null);
        iMerchantBillingInfoService.save(merchantBillingInfoEntity);
        // 3、写商户变更表
        // 3.1、初始化商户变更记录信息实体
        MerchantChangeInfoEntity merchantChangeInfoEntity = initMerchantChangeSettlementInfo(settlementInfo);
        merchantChangeInfoEntity.setChangeLinkId(merchantBillingInfoEntity.getId());
        boolean save = iMerchantChangeInfoService.save(merchantChangeInfoEntity);
        // 4、写操作日志记录表
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(settlementInfo, "修改结算信息", 2);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok(true);
    }

    /**
     * 获取变更单列表信息
     *
     * @param query 获取变更单列表信息
     * @return
     */
    @ApiOperation(value = "审核变更单信息")
    @PostMapping("/verifyMerchantChangeInfo")
    public SHttpResponse<PageRespBase<MerchantChangeInfoVo>> selectMerchantChangeInfos(@RequestBody MerchantChangeInfoQuery query) {
        // 1、根据条件查询审核变更单信息
        Page<MerchantChangeInfoEntity> page = iMerchantChangeInfoService.lambdaQuery()
                .eq(StringUtils.isNotBlank(query.getCode()), MerchantChangeInfoEntity::getCode, query.getCode())
                .like(StringUtils.isNotBlank(query.getName()), MerchantChangeInfoEntity::getName, query.getName())
                .eq(query.getChangeType() != null, MerchantChangeInfoEntity::getChangeType, query.getChangeType())
                .between(query.getSubmitStartTime() != null, MerchantChangeInfoEntity::getSubmitTime, query.getSubmitStartTime(), query.getSubmitEndTime())
                .eq(query.getChangeStatus() != null, MerchantChangeInfoEntity::getChangeStatus, query.getChangeStatus())
                .orderByDesc(MerchantChangeInfoEntity::getSubmitTime)
                .page(new Page<>(query.getPageNum(), query.getPageSize()));

        // 2、组装返回数据
        PageRespBase<MerchantChangeInfoVo> respBase = new PageRespBase<MerchantChangeInfoVo>();
        respBase.setCurrPage(query.getPageNum());
        respBase.setPageSize(query.getPageSize());
        respBase.setTotalCount(page.getTotal());
        respBase.setTotalPage(page.getTotal() % page.getSize() == 0 ? page.getTotal() / page.getSize() : page.getTotal() / page.getSize() + 1);
        List<MerchantChangeInfoVo> merchantChangeInfoVos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            page.getRecords().forEach(item -> {
                MerchantChangeInfoVo merchantChangeInfoVo = new MerchantChangeInfoVo();
                BeanUtils.copyProperties(item, merchantChangeInfoVo);
                merchantChangeInfoVos.add(merchantChangeInfoVo);
            });
        }
        respBase.setList(merchantChangeInfoVos);
        return SHttpResponse.ok(respBase);
    }


    /**
     * 审核入驻商户信息
     *
     * @param query 待审核的入驻商户信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Integer> verifyMerchantInfo(@RequestBody MerchantInfoVerifyQuery query) throws JYFException {
        // 1、更新审核状态
        boolean update = iMerchantInfoService.lambdaUpdate()
                .eq(MerchantInfoEntity::getId, query.getId())
                .set(MerchantInfoEntity::getStatus, query.getStatus() == 0 ? -2 : 1)
                .set(MerchantInfoEntity::getUpdateTime, LocalDateTime.now())
                .set(MerchantInfoEntity::getUpdateUser, "111") // TODO 登录信息
                .update();
        // 2、如果为审核通过状态，则调用扫呗创建商户信息
        if (1 == query.getStatus()) {
            // 2.1、获取当前的商户信息
            MerchantInfoEntity merchantInfoEntity = iMerchantInfoService.lambdaQuery()
                    .eq(MerchantInfoEntity::getId, query.getId())
                    .one();
            // 2.2、校验扫呗是否存在当前商户
            SaobeiMerchantCheckRequest checkRequest = new SaobeiMerchantCheckRequest();
            checkRequest.setMerchant_name(merchantInfoEntity.getName());
            checkRequest.setTrace_no(IdUtil.fastSimpleUUID());
            checkRequest.setInst_no(ApiConstants.INST_NO); // 机构号
            SaobeiMerchantCheckResponse checkResponse = saobeiMerchantManager.checkMerchantName(checkRequest);
            if (!"01".equals(checkResponse.getReturn_code())) {
                log.error("扫呗创建商户异常，检查返回结果信息为：{}", JSONObject.toJSONString(checkResponse));
                throw new JYFException(checkResponse.getReturn_msg());
            }
            // 2.1、构建扫呗创建商户信息实体
            SaobeiMerchantAddRequest merchantAddRequest = initSaobeiMerchantAddRequest(merchantInfoEntity);
            // 2.2、推送到扫呗创建商户
            SaobeiMerchantAddResponse merchantAddResponse = saobeiMerchantManager.addMerchant(merchantAddRequest);
            if (!"01".equals(merchantAddResponse.getReturn_code()) || ( "01".equals(merchantAddResponse.getReturn_code()) && !"01".equals(merchantAddResponse.getResult_code()))) {
                log.error("扫呗创建商户异常，检查返回结果信息为：{}", JSONObject.toJSONString(merchantAddResponse));
                throw new JYFException(merchantAddResponse.getReturn_msg());
            }
        }
        // 3、写操作日志
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(query, "创建扫呗商户信息", 7);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok();
    }

    /**
     * 审核入驻商户变更单信息。因基本信息直接审核通过，故此处只存在结算信息的审核
     *
     * @param query 待审核的入驻商户变更单信息
     * @return
     */
    public SHttpResponse<Integer> verifyMerchantChangeInfo(@RequestBody MerchantInfoVerifyQuery query) throws JYFException {
        // 1、更新审核状态
        boolean update = iMerchantChangeInfoService.lambdaUpdate()
                .eq(MerchantChangeInfoEntity::getId, query.getId())
                .set(MerchantChangeInfoEntity::getChangeStatus, query.getStatus())
                .set(MerchantChangeInfoEntity::getHandlerTime, LocalDateTime.now())
                .update();
        // 2、如果为审核通过状态，则调用扫呗审核结算信息
        if (1 == query.getStatus()) {
            // 2.1、获取当前的变更单信息
            MerchantChangeInfoEntity changeInfoEntity = iMerchantChangeInfoService.lambdaQuery()
                    .eq(MerchantChangeInfoEntity::getId, query.getId())
                    .one();
            // 2.2、获取当前的商户信息
            MerchantInfoEntity merchantInfoEntity = iMerchantInfoService.lambdaQuery()
                    .eq(MerchantInfoEntity::getId, changeInfoEntity.getCode())
                    .one();
            if (changeInfoEntity.getChangeType() == 0){
                // 基本信息审核
                // 2.3、获取变更的基本信息
                MerchantBaseInfoEntity baseInfoEntity = iMerchantBaseInfoService.lambdaQuery()
                        .eq(MerchantBaseInfoEntity::getId, changeInfoEntity.getChangeLinkId())
                        .one();
                BeanUtils.copyProperties(baseInfoEntity, merchantInfoEntity);
                // 2.4、更新基本信息到数据库
                iMerchantInfoService.lambdaUpdate()
                        .eq(MerchantInfoEntity::getCode, merchantInfoEntity.getCode())
                        .update(merchantInfoEntity);
            } else {
                // 结算信息审核
                // 2.3、获取变更信息
                // todo 扫呗修改商户可以后放开此处
//                MerchantBillingInfoEntity merchantBillingInfoEntity = iMerchantBillingInfoService.lambdaQuery()
//                        .eq(MerchantBillingInfoEntity::getId, changeInfoEntity.getChangeLinkId())
//                        .one();
//                BeanUtils.copyProperties(merchantBillingInfoEntity, merchantInfoEntity);
//                // 2.4、构建扫呗创建商户信息实体
//                SaobeiMerchantAddRequest merchantAddRequest = initSaobeiMerchantAddRequest(merchantInfoEntity);
//                // 2.2、推送到扫呗创建商户
//                SaobeiMerchantAddResponse merchantAddResponse = saobeiMerchantManager.addMerchant(merchantAddRequest);
//                if (!"01".equals(merchantAddResponse.getReturn_code())) {
//                    log.error("扫呗创建商户异常，检查返回结果信息为：{}", JSONObject.toJSONString(merchantAddResponse));
//                    throw new JYFException(merchantAddResponse.getReturn_msg());
//                } else {
//                    SHttpResponse<Integer> merchantInfoResponse = verifyMerchantInfoFromSB(merchantAddResponse, query);
//                    if (!merchantInfoResponse.isOk()) {
//                        log.error("处理扫呗创建商户返回信息异常，检查返回结果信息为：{}", JSONObject.toJSONString(merchantAddResponse));
//                        throw new JYFException(merchantInfoResponse.getErrmsg());
//                    }
//                }
            }
        }
        // 3、写操作日志
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(query, "平台审核入驻商户变更单", 11);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok();
    }

    /**
     * 入驻商户变更单扫呗审核后操作信息。此处进入即审核成功
     *
     * @param addResponse 入驻商户变更单扫呗审核后操作信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public SHttpResponse<Integer> verifyMerchantInfoFromSB(SaobeiMerchantAddResponse addResponse, MerchantInfoVerifyQuery query) {
        // 1、更新审核状态
        boolean update = iMerchantChangeInfoService.lambdaUpdate()
                .eq(MerchantChangeInfoEntity::getId, query.getId())
                .set(MerchantChangeInfoEntity::getChangeStatus, 3)
                .set(MerchantChangeInfoEntity::getHandlerTime, LocalDateTime.now())
                .update();
        // 2、如果为审核通过状态,则更新变更新信息到入驻商户表
//        if (0 == query.getStatus()){
        // 2.1、获取变更单信息
        MerchantChangeInfoEntity merchantChangeInfo = iMerchantChangeInfoService.getById(query.getId());
        // 2.2、获取变更信息
        MerchantBillingInfoEntity merchantBillingInfoEntity = iMerchantBillingInfoService.lambdaQuery()
                .eq(MerchantBillingInfoEntity::getMerchantId, merchantChangeInfo.getCode())
                .ne(MerchantBillingInfoEntity::getStatus, 3)
                .one();
        // 2.3、组装入驻商户更新信息
        MerchantInfoEntity merchantInfoEntity = new MerchantInfoEntity();
        BeanUtils.copyProperties(merchantBillingInfoEntity, merchantInfoEntity);
        // 2.4、更入驻商户信息
        update = iMerchantInfoService.lambdaUpdate()
                .eq(MerchantInfoEntity::getCode, merchantChangeInfo.getCode())
                .update(merchantInfoEntity);
//        }
        // 3、写操作日志
        MerchantOperLogEntity merchantOperLogEntity = initMerchantOperLog(query, "入驻商户变更单扫呗审核结束", 9);
        iMerchantOperLogService.save(merchantOperLogEntity);
        return SHttpResponse.ok(1);
    }

    /********************************************************* private **********************************************************/

    /**
     * 通过数据实体构建结算变更单信息(显示使用)
     *
     * @param newBaseInfo
     * @return
     */
    private MerchantSettlementInfosVo initMerchantSettlementInfosVo(MerchantBillingInfoEntity newBaseInfo){
        MerchantSettlementInfosVo baseInfosVo = new MerchantSettlementInfosVo();
        MerchantSettlementInfoVo newBaseInfoVo = new MerchantSettlementInfoVo();
        BeanUtils.copyProperties(newBaseInfo, newBaseInfoVo);
        baseInfosVo.setNewSettlementInfo(newBaseInfoVo);
        MerchantSettlementInfoVo oldBaseInfoVo = new MerchantSettlementInfoVo();
        oldBaseInfoVo.setBankAddress(newBaseInfo.getBankAddressOld());
        oldBaseInfoVo.setBankAccountCode(newBaseInfo.getBankAccountCodeOld());
        oldBaseInfoVo.setBankAccountName(newBaseInfo.getBankAccountNameOld());
        oldBaseInfoVo.setBankInfo(newBaseInfo.getBankInfoOld());
        oldBaseInfoVo.setBankBranch(newBaseInfo.getBankBranchOld());
        oldBaseInfoVo.setBankCardSecondImg(newBaseInfo.getBankCardSecondImgOld());
        oldBaseInfoVo.setBankCardFirstImg(newBaseInfo.getBankCardFirstImgOld());
        oldBaseInfoVo.setBankPhoneNum(newBaseInfo.getBankPhoneNumOld());
        baseInfosVo.setOldSettlementInfo(oldBaseInfoVo);
        return baseInfosVo;
    }

    /**
     * 通过数据实体构建变更单信息(保存使用)
     *
     * @param billingInfoEntity
     * @return
     */
    private MerchantBillingInfoEntity initMerchantBillingInfoEntity(MerchantBillingInfoEntity billingInfoEntity, MerchantInfoEntity merchantInfoEntity){
        billingInfoEntity.setBankAddressOld(merchantInfoEntity.getBankAddress());
        billingInfoEntity.setBankAccountCodeOld(merchantInfoEntity.getBankAccountCode());
        billingInfoEntity.setBankAccountNameOld(merchantInfoEntity.getBankAccountName());
        billingInfoEntity.setBankInfoOld(merchantInfoEntity.getBankInfo());
        billingInfoEntity.setBankBranchOld(merchantInfoEntity.getBankBranch());
        billingInfoEntity.setBankCardSecondImgOld(merchantInfoEntity.getBankCardSecondImg());
        billingInfoEntity.setBankCardFirstImgOld(merchantInfoEntity.getBankCardFirstImg());
        billingInfoEntity.setBankPhoneNumOld(merchantInfoEntity.getBankPhoneNum());
        return billingInfoEntity;
    }

    /**
     * 通过数据实体构建基本信息变更单信息(显示使用)
     *
     * @param baseInfo
     * @return
     */
    private MerchantManageBaseInfosVo initMerchantManageBaseInfosVo(MerchantBaseInfoEntity baseInfo){
        MerchantManageBaseInfosVo baseInfosVo = new MerchantManageBaseInfosVo();
        MerchantManageBaseInfoVo newBaseInfoVo = new MerchantManageBaseInfoVo();
        BeanUtils.copyProperties(baseInfo, newBaseInfoVo);
        baseInfosVo.setNewBaseInfo(newBaseInfoVo);
        MerchantManageBaseInfoVo oldBaseInfoVo = new MerchantManageBaseInfoVo();
        oldBaseInfoVo.setName(baseInfo.getNameOld());
        oldBaseInfoVo.setAbbreviationName(baseInfo.getAbbreviationNameOld());
        oldBaseInfoVo.setMobile(baseInfo.getMobileOld());
        oldBaseInfoVo.setCategoryCode(baseInfo.getCategoryCodeOld());
        oldBaseInfoVo.setCategoryName(baseInfo.getCategoryNameOld());
        oldBaseInfoVo.setAddressCode(baseInfo.getAddressCodeOld());
        oldBaseInfoVo.setAddressName(baseInfo.getAddressNameOld());
        oldBaseInfoVo.setDetailedAddress(baseInfo.getDetailedAddressOld());
        oldBaseInfoVo.setContactsName(baseInfo.getContactsNameOld());
        oldBaseInfoVo.setContactsEmaill(baseInfo.getContactsEmaillOld());
        baseInfosVo.setOldBaseInfo(oldBaseInfoVo);
        return baseInfosVo;
    }

    /**
     * 通过数据实体构建变更单信息(保存使用)
     *
     * @param baseInfo
     * @return
     */
    private MerchantBaseInfoEntity initMerchantManageBaseInfoEntity(MerchantBaseInfoEntity baseInfo, MerchantInfoEntity merchantInfoEntity){
        baseInfo.setNameOld(merchantInfoEntity.getName());
        baseInfo.setAbbreviationNameOld(merchantInfoEntity.getAbbreviationName());
        baseInfo.setMobileOld(merchantInfoEntity.getMobile());
        baseInfo.setCategoryCodeOld(merchantInfoEntity.getCategoryCode());
        baseInfo.setCategoryNameOld(merchantInfoEntity.getCategoryName());
        baseInfo.setAddressCodeOld(merchantInfoEntity.getAddressCode());
        baseInfo.setAddressNameOld(merchantInfoEntity.getAddressName());
        baseInfo.setDetailedAddressOld(merchantInfoEntity.getDetailedAddress());
        baseInfo.setContactsNameOld(merchantInfoEntity.getContactsName());
        baseInfo.setContactsEmaillOld(merchantInfoEntity.getContactsEmaill());
        return baseInfo;
    }

    /**
     * 通过入驻商户信息构建扫呗商户信息
     *
     * @param merchantInfoEntity
     * @return
     */
    private SaobeiMerchantAddRequest initSaobeiMerchantAddRequest(MerchantInfoEntity merchantInfoEntity) {
        SaobeiMerchantAddRequest request = new SaobeiMerchantAddRequest();
        request.setInst_no(ApiConstants.INST_NO);
        request.setTrace_no(RandomUtils.getRandom(32));
        request.setMerchant_name(merchantInfoEntity.getName());
        request.setMerchant_alias(merchantInfoEntity.getAbbreviationName());
        request.setMerchant_company(merchantInfoEntity.getName());
        // 获取区级别数据
        String[] areaCodes = merchantInfoEntity.getAddressCode().split(",");
        SAreaEntity areaEntity = isAreaService.lambdaQuery()
                .eq(SAreaEntity::getAreaCode, areaCodes[2])
                .eq(SAreaEntity::getAreaLevel, 3)
                .one();
        request.setMerchant_county(areaEntity.getAreaName());
        request.setMerchant_county_code(areaEntity.getAreaCode());
        areaEntity = isAreaService.lambdaQuery()
                .eq(SAreaEntity::getAreaCode, areaCodes[1])
                .eq(SAreaEntity::getAreaLevel, 2)
                .one();
        request.setMerchant_city(areaEntity.getAreaName());
        request.setMerchant_city_code(areaEntity.getAreaCode());
        areaEntity = isAreaService.lambdaQuery()
                .eq(SAreaEntity::getAreaCode, areaCodes[0])
                .eq(SAreaEntity::getAreaLevel, 1)
                .one();
        request.setMerchant_province(areaEntity.getAreaName());
        request.setMerchant_province_code(areaEntity.getAreaCode());
        request.setMerchant_address(merchantInfoEntity.getDetailedAddress());
        request.setMerchant_person(merchantInfoEntity.getContactsName());
        request.setMerchant_phone(merchantInfoEntity.getMobile());
        request.setMerchant_email(merchantInfoEntity.getContactsEmaill());
        request.setMerchant_service_phone(merchantInfoEntity.getCustomerServiceNumber());
        request.setBusiness_name(merchantInfoEntity.getCategoryName());
        String[] businessCodes = merchantInfoEntity.getCategoryCode().split(",");
        request.setBusiness_code(businessCodes[businessCodes.length - 1]);
        // 入网类型(1企业、2个体工商户、3小微
        request.setMerchant_business_type((merchantInfoEntity.getType() + 1) + "");
        // 账号类型：1:对公  2：对私
        request.setAccount_type(merchantInfoEntity.getBillingType() > 0 ? "2" : "1");
        // 结算类型：1.法人结算 2.非法人结算
        request.setSettlement_type(merchantInfoEntity.getBillingType() == 2 ? "2" : "1");
        // 默认为“营业执照”
        request.setLicense_type("0");
        request.setAccount_name(merchantInfoEntity.getBankAccountName());
        request.setAccount_no(merchantInfoEntity.getBankAccountCode());
        request.setAccount_phone(merchantInfoEntity.getBankPhoneNum());
        request.setBank_name(merchantInfoEntity.getBankInfo());
        request.setImg_bankcard_a(merchantInfoEntity.getBankCardFirstImg());
        request.setImg_bankcard_b(merchantInfoEntity.getBankCardSecondImg());
        // 清算类型 默认为自动结算
        request.setSettle_type("1");
        request.setMerchant_id_no(merchantInfoEntity.getSettlementPersonCardCode());
        request.setImg_license(merchantInfoEntity.getBusinessLicenseImg());
        request.setArtif_nm(merchantInfoEntity.getContactsName());

        request.setLicense_no(merchantInfoEntity.getRegistrationCode());
        request.setLegalIdnum(merchantInfoEntity.getLegalPersonCardCode());
        request.setImg_idcard_a(merchantInfoEntity.getLegalPersonCardFirstImg());
        request.setImg_idcard_b(merchantInfoEntity.getLegalPersonCardSecondImg());
        request.setImg_logo(merchantInfoEntity.getMerchantLog());
        request.setImg_indoor(merchantInfoEntity.getStoreReception());
        request.setImg_open_permits(merchantInfoEntity.getAccountPermit());
        // TODO
        request.setBank_no("308521015055");
        // todo 组织机构代码证照片(非三证合一)
        request.setImg_org_code("111");
        // todo 税务登记证照片(非三证合一)
        request.setImg_tax_reg("111");
        // 固定税率即可
        request.setRate_code("M0030");
        // 根据不同入网类型、账号类型、计算类型过滤掉不同数据
        if (merchantInfoEntity.getType() == 0){
            // 企业
            request.setMerchant_id_no(null);
        }
        if (merchantInfoEntity.getType() == 2){
            // 小微商户
        }
        if (merchantInfoEntity.getType() == 2){
            // 小微商户
        }
        return request;
    }


    /**
     * 根据商户基本信息初始化变更单
     *
     * @param merchantBaseInfoVo
     * @return
     */
    private MerchantChangeInfoEntity initMerchantChangeInfo(MerchantBaseInfoVo merchantBaseInfoVo) {
        return initMerchantChangeInfo(merchantBaseInfoVo, "基本信息变更", 0, 3);
    }

    /**
     * 根据结算信息初始化变更单
     *
     * @param settlementInfo
     * @return
     */
    private MerchantChangeInfoEntity initMerchantChangeSettlementInfo(MerchantSettlementInfoDto settlementInfo) {
        return initMerchantChangeInfo(settlementInfo, "结算信息变更", 1, 0);
    }

    /**
     * 初始化变更单
     *
     * @param baseInfoDomain
     * @param changeDesc
     * @param changeType
     * @param changeStatus
     * @return
     */
    private MerchantChangeInfoEntity initMerchantChangeInfo(BaseInfoDomain baseInfoDomain, String changeDesc, int changeType, int changeStatus) {
        MerchantChangeInfoEntity merchantChangeInfoEntity = new MerchantChangeInfoEntity();
        merchantChangeInfoEntity.setChangeDesc(changeDesc);
        // 结算信息需要审核
        merchantChangeInfoEntity.setChangeStatus(changeStatus);
        merchantChangeInfoEntity.setChangeType(changeType);
        // 当前登录人ID
        merchantChangeInfoEntity.setChangeUser(111);
        merchantChangeInfoEntity.setCode(baseInfoDomain.getCode());
        merchantChangeInfoEntity.setName(baseInfoDomain.getName());
        LocalDateTime now = LocalDateTime.now();
        merchantChangeInfoEntity.setSubmitTime(now);
        merchantChangeInfoEntity.setHandlerTime(now);
        return merchantChangeInfoEntity;
    }

    /**
     * 初始化操作日志信息
     *
     * @param baseInfoDomain
     * @param operDesc       操作描述
     * @param operType       操作类型
     * @return
     */
    private MerchantOperLogEntity initMerchantOperLog(BaseInfoDomain baseInfoDomain, String operDesc, Integer operType) {
        MerchantOperLogEntity merchantOperLogEntity = new MerchantOperLogEntity();
        merchantOperLogEntity.setMerchantNo(baseInfoDomain.getCode());
        merchantOperLogEntity.setRemark(operDesc);
        LocalDateTime now = LocalDateTime.now();
        merchantOperLogEntity.setOperTime(now);
        merchantOperLogEntity.setOperType(operType);
        return merchantOperLogEntity;
    }
}
